package com.quanxiaoha.weblog.web.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.quanxiaoha.weblog.common.domain.dos.*;
import com.quanxiaoha.weblog.common.domain.mapper.*;
import com.quanxiaoha.weblog.common.enums.BehaviorTypeEnum;
import com.quanxiaoha.weblog.common.utils.Response;
import com.quanxiaoha.weblog.web.model.vo.article.FindIndexArticlePageListRspVO;
import com.quanxiaoha.weblog.web.model.vo.category.FindCategoryListRspVO;
import com.quanxiaoha.weblog.web.model.vo.tag.FindTagListRspVO;
import com.quanxiaoha.weblog.web.service.RecommendationService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 推荐服务实现类
 */
@Service
@Slf4j
public class RecommendationServiceImpl implements RecommendationService {

    @Autowired
    private UserBehaviorMapper userBehaviorMapper;

    @Autowired
    private UserStatisticsMapper userStatisticsMapper;

    @Autowired
    private ArticleMapper articleMapper;

    @Autowired
    private ArticleCategoryRelMapper articleCategoryRelMapper;

    @Autowired
    private ArticleTagRelMapper articleTagRelMapper;

    @Autowired
    private CategoryMapper categoryMapper;

    @Autowired
    private TagMapper tagMapper;

    @Override
    public Response getPersonalizedRecommendations(Long userId, int limit) {
        try {
            // 1. 获取用户的历史行为
            List<UserBehaviorDO> userBehaviors = userBehaviorMapper.selectByUserId(userId);
            
            if (CollectionUtils.isEmpty(userBehaviors)) {
                // 如果用户没有历史行为，返回热门推荐
                return getPopularRecommendations(limit);
            }

            // 2. 基于协同过滤找到相似用户
            List<Long> similarUsers = findSimilarUsers(userId, userBehaviors, 10);
            
            // 3. 获取相似用户喜欢的文章
            Set<Long> recommendedArticleIds = new HashSet<>();
            Set<Long> userReadArticleIds = userBehaviors.stream()
                    .map(UserBehaviorDO::getArticleId)
                    .collect(Collectors.toSet());

            for (Long similarUserId : similarUsers) {
                List<UserBehaviorDO> similarUserBehaviors = userBehaviorMapper.selectByUserId(similarUserId);
                for (UserBehaviorDO behavior : similarUserBehaviors) {
                    // 排除用户已经浏览过的文章
                    if (!userReadArticleIds.contains(behavior.getArticleId())) {
                        recommendedArticleIds.add(behavior.getArticleId());
                    }
                }
                
                if (recommendedArticleIds.size() >= limit * 2) {
                    break; // 获取足够的候选文章
                }
            }

            // 4. 如果协同过滤推荐的文章不够，补充基于内容的推荐
            if (recommendedArticleIds.size() < limit) {
                Set<Long> contentBasedRecommendations = getContentBasedRecommendations(userId, userBehaviors, limit - recommendedArticleIds.size());
                recommendedArticleIds.addAll(contentBasedRecommendations);
            }

            // 5. 获取推荐文章的详细信息
            List<FindIndexArticlePageListRspVO> recommendedArticles = getArticleDetails(new ArrayList<>(recommendedArticleIds), limit);

            return Response.success(recommendedArticles);

        } catch (Exception e) {
            log.error("获取个性化推荐失败", e);
            return getPopularRecommendations(limit);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Response recordUserBehavior(Long userId, Long articleId, Integer behaviorType) {
        try {
            BehaviorTypeEnum behaviorEnum = BehaviorTypeEnum.getByCode(behaviorType);
            if (behaviorEnum == null) {
                return Response.fail("无效的行为类型");
            }

            // 检查是否已存在相同的行为记录
            UserBehaviorDO existingBehavior = userBehaviorMapper.selectByUserAndArticle(userId, articleId, behaviorType);
            if (existingBehavior != null) {
                // 如果是浏览行为，更新时间；其他行为不重复记录
                if (behaviorType.equals(BehaviorTypeEnum.VIEW.getCode())) {
                    existingBehavior.setCreateTime(LocalDateTime.now());
                    userBehaviorMapper.updateById(existingBehavior);
                }
                return Response.success();
            }

            // 记录新的行为
            UserBehaviorDO behavior = UserBehaviorDO.builder()
                    .userId(userId)
                    .articleId(articleId)
                    .behaviorType(behaviorType)
                    .behaviorScore(behaviorEnum.getDefaultScore())
                    .createTime(LocalDateTime.now())
                    .build();

            userBehaviorMapper.insert(behavior);

            // 更新用户统计数据
            updateUserStatistics(userId, behaviorType);

            // 更新文章作者的统计数据
            ArticleDO article = articleMapper.selectById(articleId);
            if (article != null && article.getUserId() != null) {
                updateAuthorStatistics(article.getUserId(), behaviorType);
            }

            return Response.success();

        } catch (Exception e) {
            log.error("记录用户行为失败", e);
            return Response.fail("记录行为失败");
        }
    }

    @Override
    public Response getPopularRecommendations(int limit) {
        try {
            // 获取最近30天内浏览量最高的文章
            LambdaQueryWrapper<ArticleDO> wrapper = Wrappers.<ArticleDO>lambdaQuery()
                    .ge(ArticleDO::getCreateTime, LocalDateTime.now().minusDays(30))
                    .orderByDesc(ArticleDO::getReadNum)
                    .orderByDesc(ArticleDO::getCreateTime)
                    .last("LIMIT " + limit);

            List<ArticleDO> popularArticles = articleMapper.selectList(wrapper);
            List<Long> articleIds = popularArticles.stream().map(ArticleDO::getId).collect(Collectors.toList());
            
            List<FindIndexArticlePageListRspVO> result = getArticleDetails(articleIds, limit);
            return Response.success(result);

        } catch (Exception e) {
            log.error("获取热门推荐失败", e);
            return Response.fail("获取推荐失败");
        }
    }

    @Override
    public Response getSimilarArticleRecommendations(Long articleId, int limit) {
        try {
            // 获取当前文章的分类和标签
            ArticleDO currentArticle = articleMapper.selectById(articleId);
            if (currentArticle == null) {
                return Response.success(Collections.emptyList());
            }

            // 获取相同分类的文章
            ArticleCategoryRelDO categoryRel = articleCategoryRelMapper.selectByArticleId(articleId);
            List<Long> similarArticleIds = new ArrayList<>();
            
            if (categoryRel != null) {
                List<ArticleCategoryRelDO> sameCategoryArticles = articleCategoryRelMapper.selectByCategoryId(categoryRel.getCategoryId());
                similarArticleIds = sameCategoryArticles.stream()
                        .map(ArticleCategoryRelDO::getArticleId)
                        .filter(id -> !id.equals(articleId))
                        .collect(Collectors.toList());
            }

            // 如果同分类文章不够，补充相同标签的文章
            if (similarArticleIds.size() < limit) {
                List<ArticleTagRelDO> tagRels = articleTagRelMapper.selectByArticleId(articleId);
                for (ArticleTagRelDO tagRel : tagRels) {
                    List<ArticleTagRelDO> sameTagArticles = articleTagRelMapper.selectByTagId(tagRel.getTagId());
                    for (ArticleTagRelDO sameTagRel : sameTagArticles) {
                        if (!sameTagRel.getArticleId().equals(articleId) && !similarArticleIds.contains(sameTagRel.getArticleId())) {
                            similarArticleIds.add(sameTagRel.getArticleId());
                        }
                    }
                    
                    if (similarArticleIds.size() >= limit * 2) {
                        break;
                    }
                }
            }

            List<FindIndexArticlePageListRspVO> result = getArticleDetails(similarArticleIds, limit);
            return Response.success(result);

        } catch (Exception e) {
            log.error("获取相似文章推荐失败", e);
            return Response.fail("获取推荐失败");
        }
    }

    /**
     * 查找相似用户（简化版协同过滤）
     */
    private List<Long> findSimilarUsers(Long userId, List<UserBehaviorDO> userBehaviors, int limit) {
        // 获取当前用户浏览过的文章ID
        Set<Long> userArticleIds = userBehaviors.stream()
                .map(UserBehaviorDO::getArticleId)
                .collect(Collectors.toSet());

        if (userArticleIds.isEmpty()) {
            return new ArrayList<>();
        }

        // 查找浏览过相同文章的其他用户
        Map<Long, Integer> userSimilarity = new HashMap<>();

        for (Long articleId : userArticleIds) {
            List<UserBehaviorDO> articleBehaviors = userBehaviorMapper.selectByArticleId(articleId);
            for (UserBehaviorDO behavior : articleBehaviors) {
                if (!behavior.getUserId().equals(userId)) {
                    userSimilarity.merge(behavior.getUserId(), 1, Integer::sum);
                }
            }
        }

        // 按相似度排序并返回前N个用户
        return userSimilarity.entrySet().stream()
                .sorted(Map.Entry.<Long, Integer>comparingByValue().reversed())
                .limit(limit)
                .map(Map.Entry::getKey)
                .collect(Collectors.toList());
    }

    /**
     * 基于内容的推荐
     */
    private Set<Long> getContentBasedRecommendations(Long userId, List<UserBehaviorDO> userBehaviors, int limit) {
        // 分析用户偏好的分类和标签
        Map<Long, Integer> categoryPreferences = new HashMap<>();
        Map<Long, Integer> tagPreferences = new HashMap<>();

        for (UserBehaviorDO behavior : userBehaviors) {
            // 获取文章的分类
            ArticleCategoryRelDO categoryRel = articleCategoryRelMapper.selectByArticleId(behavior.getArticleId());
            if (categoryRel != null) {
                categoryPreferences.merge(categoryRel.getCategoryId(), behavior.getBehaviorScore().intValue(), Integer::sum);
            }

            // 获取文章的标签
            List<ArticleTagRelDO> tagRels = articleTagRelMapper.selectByArticleId(behavior.getArticleId());
            for (ArticleTagRelDO tagRel : tagRels) {
                tagPreferences.merge(tagRel.getTagId(), behavior.getBehaviorScore().intValue(), Integer::sum);
            }
        }

        // 根据偏好推荐文章
        Set<Long> recommendedIds = new HashSet<>();
        
        // 推荐偏好分类的文章
        categoryPreferences.entrySet().stream()
                .sorted(Map.Entry.<Long, Integer>comparingByValue().reversed())
                .limit(3)
                .forEach(entry -> {
                    List<ArticleCategoryRelDO> categoryArticles = articleCategoryRelMapper.selectByCategoryId(entry.getKey());
                    categoryArticles.stream()
                            .map(ArticleCategoryRelDO::getArticleId)
                            .limit(limit / 2)
                            .forEach(recommendedIds::add);
                });

        return recommendedIds;
    }

    /**
     * 获取文章详细信息
     */
    private List<FindIndexArticlePageListRspVO> getArticleDetails(List<Long> articleIds, int limit) {
        if (CollectionUtils.isEmpty(articleIds)) {
            return Collections.emptyList();
        }

        List<ArticleDO> articles = articleMapper.selectBatchIds(articleIds.stream().limit(limit).collect(Collectors.toList()));

        return articles.stream().map(article -> {
            FindIndexArticlePageListRspVO vo = new FindIndexArticlePageListRspVO();
            vo.setId(article.getId());
            vo.setTitle(article.getTitle());
            vo.setCover(article.getCover());
            vo.setSummary(article.getSummary());
            vo.setCreateDate(article.getCreateTime().toLocalDate());
            vo.setIsTop(false); // 默认不置顶

            // 获取分类信息
            ArticleCategoryRelDO categoryRel = articleCategoryRelMapper.selectByArticleId(article.getId());
            if (categoryRel != null) {
                CategoryDO category = categoryMapper.selectById(categoryRel.getCategoryId());
                if (category != null) {
                    FindCategoryListRspVO categoryVO = FindCategoryListRspVO.builder()
                            .id(category.getId())
                            .name(category.getName())
                            .build();
                    vo.setCategory(categoryVO);
                }
            }

            // 获取标签信息
            List<ArticleTagRelDO> tagRels = articleTagRelMapper.selectByArticleId(article.getId());
            if (!CollectionUtils.isEmpty(tagRels)) {
                List<TagDO> tags = tagMapper.selectBatchIds(
                        tagRels.stream().map(ArticleTagRelDO::getTagId).collect(Collectors.toList())
                );
                List<FindTagListRspVO> tagVOs = tags.stream().map(tag ->
                    FindTagListRspVO.builder()
                            .id(tag.getId())
                            .name(tag.getName())
                            .build()
                ).collect(Collectors.toList());
                vo.setTags(tagVOs);
            }

            return vo;
        }).collect(Collectors.toList());
    }

    /**
     * 更新用户统计数据
     */
    private void updateUserStatistics(Long userId, Integer behaviorType) {
        UserStatisticsDO statistics = userStatisticsMapper.selectByUserId(userId);
        if (statistics == null) {
            // 创建新的统计记录
            statistics = UserStatisticsDO.builder()
                    .userId(userId)
                    .totalArticles(0L)
                    .totalViews(0L)
                    .totalLikes(0L)
                    .totalFavorites(0L)
                    .totalComments(0L)
                    .createTime(LocalDateTime.now())
                    .updateTime(LocalDateTime.now())
                    .build();
            userStatisticsMapper.insert(statistics);
        }

        // 根据行为类型更新对应的统计数据
        if (behaviorType.equals(BehaviorTypeEnum.VIEW.getCode())) {
            userStatisticsMapper.increaseViewCount(userId, 1);
        } else if (behaviorType.equals(BehaviorTypeEnum.LIKE.getCode())) {
            userStatisticsMapper.increaseLikeCount(userId, 1);
        } else if (behaviorType.equals(BehaviorTypeEnum.FAVORITE.getCode())) {
            userStatisticsMapper.increaseFavoriteCount(userId, 1);
        }
    }

    /**
     * 更新文章作者的统计数据
     */
    private void updateAuthorStatistics(Long authorId, Integer behaviorType) {
        if (behaviorType.equals(BehaviorTypeEnum.VIEW.getCode())) {
            userStatisticsMapper.increaseViewCount(authorId, 1);
        } else if (behaviorType.equals(BehaviorTypeEnum.LIKE.getCode())) {
            userStatisticsMapper.increaseLikeCount(authorId, 1);
        } else if (behaviorType.equals(BehaviorTypeEnum.FAVORITE.getCode())) {
            userStatisticsMapper.increaseFavoriteCount(authorId, 1);
        }
    }
}
